﻿using Ldt.SettingCenter.Core;
using LdtJudge.DataEngine.CallInterface.ConfigLog;
using LdtJudge.DataEngine.CallInterface.ConfigManager;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;

namespace LdtJudge.DataEngine.CallInterface.ConfiCenter
{
    /// <summary>
    /// 配置中心相关信息操作类
    /// </summary>
    public  class ConfigRetrieval: IConfigRetrieval
    {

        public static ConfigRetrieval GetConfigRetrieval { get => _configRetrieval; set => _configRetrieval = value; }
        private static ConfigRetrieval _configRetrieval;
        /// <summary>
        /// 配置文件对象
        /// </summary>
        private IConfiguration _configuration;

        public ConfigManagerHandle ConfigManagerHandle { get; }
        /// <summary>
        /// 配置中心处理对象
        /// </summary>
        private ISettingCenter settingCenter;
        /// <summary>
        /// 初始化配置中心读取配置信息
        /// </summary>
        /// <param name="configuration">配置对象</param>
        /// <param name="configManagerHandle">配置数据载体</param>
        public ConfigRetrieval(IConfiguration configuration, ConfigManagerHandle configManagerHandle,ISettingCenter _settingCenter)
        {
            if (configuration == null)
            {
                _configuration = new ConfigurationBuilder().SetBasePath(System.AppContext.BaseDirectory).AddJsonFile("appsettings.json", true, true).Build();
            }
            else
            {
                _configuration = configuration;
            }
            //将配置中心对象赋值
            settingCenter= _settingCenter;
            //创建基础的对象
            ConfigManagerHandle = configManagerHandle;
            //进行初始化相关读取配置操作；
            InIt();
            _configRetrieval = this;
        }
        
        /// <summary>
        /// 数据库连接字符串
        /// </summary>
        private ConcurrentDictionary<string, Tuple<string, string>> concurrentConnectionStringDic = new ConcurrentDictionary<string, Tuple<string, string>>();
        /// <summary>
        /// 获取当前配置中心的API接口
        /// </summary>
        //private Dictionary<string, Tuple<string, string>> apiDic = new Dictionary<string, Tuple<string, string>>();
        /// <summary>
        /// 获取自定义配置数据
        /// </summary>
        private ConcurrentDictionary<string, Tuple<string, string>> appSetingDic = new ConcurrentDictionary<string, Tuple<string, string>>();
        /// <summary>
        /// 日志目录
        /// </summary>
        private string baseLogPath = string.Empty;

        /// <summary>
        /// 数据集合
        /// </summary>
        private readonly string[] databaselist = new string[2] { "Ldt_JudgeDocSystem", "LdtCommonManage"};

        /// <summary>
        /// 是否Linux下运行
        /// </summary>
        private bool IsLinux
        {
            get => System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux);
        }

       
        /// <summary>
        /// 获取自定义key-value数据信息
        /// </summary>
        /// <param name="appstrkey">key</param>
        /// <returns></returns>
        public string GetAppSettingString(string appstrkey)
        {
            appstrkey = appstrkey.ToLower();
            if (appSetingDic.ContainsKey(appstrkey))
            {
                if (appSetingDic[appstrkey]!=null)
                {
                    return appSetingDic[appstrkey].Item1;
                }
                else
                {
                    return string.Empty;
                }
                
            }
            else
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// 获取数据库连接信息
        /// </summary>
        /// <param name="connectionName">数据库名称</param>
        /// <returns></returns>
        public string GetConnectionString(string connectionName)
        {
            connectionName = connectionName.ToLower();
            if (concurrentConnectionStringDic.ContainsKey(connectionName))
            {
                return concurrentConnectionStringDic[connectionName].Item1;
            }
            else
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 获取日志输出路径
        /// </summary>
        /// <returns></returns>
        public string GetLogPath()
        {
            return baseLogPath;
        }

        /// <summary>
        /// 修改指定key的value值内容
        /// </summary>
        /// <param name="appstrkey">指定key</param>
        /// <param name="appstrkeyValue">对应值</param>
        /// <returns></returns>
        public bool SetAppSettingString(string appstrkey, string appstrkeyValue)
        {
            appstrkey = appstrkey.ToLower();
            if (appSetingDic.ContainsKey(appstrkey))
            {
                var appkey = appSetingDic[appstrkey];
                appSetingDic.TryUpdate(appstrkey, new Tuple<string, string>(appstrkeyValue, appkey.Item2), appkey);
                return true;
            }
            return false;
        }
        /// <summary>
        /// 修改指定数据库的连接字符串
        /// </summary>
        /// <param name="connectionName">数据库名称</param>
        /// <param name="connectionValue">数据库连接字符串</param>
        /// <returns></returns>
        public bool SetConnectionString(string connectionName, string connectionValue)
        {
            if (concurrentConnectionStringDic.ContainsKey(connectionName.ToLower()))
            {
                var connstr = concurrentConnectionStringDic[connectionName.ToLower()];
                concurrentConnectionStringDic.TryUpdate(connectionName.ToLower(), new Tuple<string, string>(connectionValue, connstr.Item2), connstr);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 进行远程获取配置文件内容
        /// </summary>
        /// <param name="sysCode">系统编号，这里目前是wordparse、ldt_judgedocsystem、</param>
        /// <param name="modelPath">模块路径</param>
        /// <param name="fileName">文件名称</param>
        /// <param name="fileType">文件类型</param>
        /// <returns>远程调用获取的内容</returns>
        public  string GetRemoteFileContent(string sysCode, string modelPath, string fileName, string fileType)
        {
            return LawConfigFileClass.FileClient.GetFileClient(ConfigManagerHandle.Settingcenter).getfilecontent(sysCode, modelPath, fileName, fileType);
        }


        /// <summary>
        /// 更新指定产品的信息
        /// </summary>
        /// <param name="appstrkey">产品key</param>
        /// <returns></returns>
        public bool UpdateAppSettingInfo(string appstrkey)
        {
            switch (appstrkey.ToLower())
            {
                case "wordparseapi":
                    //获取日志输出等级
                    var apploglevel = settingCenter.GetApplicationInfo("WordParseAPI");
                    if (apploglevel!=null)
                    {
                        var loglevel = apploglevel.Properties.FirstOrDefault(row => row.Key.ToLower() == "loglevel");
                        if (!loglevel.Equals(default(KeyValuePair<string,Tuple<string,string>>)))
                        {
                            //appSetingDic.AddOrUpdate("loglevel", new Tuple<string, string>(loglevel.Key, ""), (key, returnvalue) => returnvalue = new Tuple<string, string>(loglevel.value, ""));
                            appSetingDic.AddOrUpdate("loglevel", loglevel.Value, (key, returnvalue) => returnvalue = loglevel.Value);
                        }
                        else
                        {
                            LogFileWriteMessage.WriteLogs(MessageType.Error, "更新产品调用配置获取日志输出等级错误，没有获取到配置中心日志输出等级配置");
                        }
                    }
                    else
                    {
                        LogFileWriteMessage.WriteLogs(MessageType.Error, "更新产品调用配置[WordParseAPI]获取日志输出等级错误，错误!");
                    }
                    break;
                case "logstash":
                    var applogtcpadr = settingCenter.GetApplicationInfo("Logstash");
                    if (applogtcpadr!=null)
                    {
                        var port=applogtcpadr.Properties["port"];
                        string url = "tcp://" + applogtcpadr.ServerIp + ":" + port.Item1;
                        appSetingDic.AddOrUpdate("logstash", new Tuple<string, string>(url, ""), (key, returnvalue) => returnvalue = new Tuple<string, string>(url, ""));
                    }
                    else
                    {
                        LogFileWriteMessage.WriteLogs(MessageType.Error, "调用配置获取[Logstash]日志输出路径错误，错误!");
                    }
                    break;
                case "swaggeruidandpwd":
                    var swaggerUserPwd = settingCenter.GetApplicationInfo("CommonSetting");
                    Tuple<string, string> swaggerAuth = swaggerUserPwd.Properties.Where(a => a.Key.ToLower() == "SwaggerUidAndPwd".ToLower())?.First().Value;
                    appSetingDic.AddOrUpdate("swaggeruidandpwd", swaggerAuth,(key, returnvalue) => returnvalue = swaggerAuth);
                    break;
                case "district":
                    var xzzfService = settingCenter.GetApplicationInfo("LdtXzzfService");
                    if(xzzfService!=null)
                    {
                        Tuple<string, string> district = xzzfService.Properties.Where(a => a.Key.ToLower() == "district".ToLower())?.FirstOrDefault().Value;
                        if(district!=null && !string.IsNullOrWhiteSpace(district.Item1))
                        {
                            appSetingDic.AddOrUpdate("district", district, (key, returnvalue) => returnvalue = district);
                        }
                        
                    }
                    break;
                default:
                    //更新指定的产品key
                    var appmodeUrl = settingCenter.GetApplicationInfo(appstrkey);
                    if (appmodeUrl!=null)
                    {
                        string url = "http://"+appmodeUrl.ServerIp+":"+appmodeUrl.Properties["port"].Item1;
                        string urlcode = appmodeUrl.Code;

                        appSetingDic.AddOrUpdate(urlcode.ToLower(), new Tuple<string, string>(url, ""), (key, returnvalue) => returnvalue = new Tuple<string, string>(url, ""));
                    }
                    else
                    {
                        LogFileWriteMessage.WriteLogs(MessageType.Error, $"更新产品{appstrkey}的数据错误，错误!");
                    }
                    break;
            }

            return true;
        }

        /// <summary>
        /// 初始化内容
        /// </summary>
        private void InIt()
        {
            //2019-04-11 关于初始化配置数据集合，只进行初始化一次。
            if (!ConfigManagerHandle.IsLoadLocalDataConfig)
            {
                try
                {
                    //赋值配置中心地址
                    //SettingCenterClient.SettingCenterAddress = ConfigManagerHandle.Settingcenter;
                    //获取数据连接配置地址
                    foreach (var basename in databaselist)
                    {
                        var strmo = settingCenter.GetDbConfigInfo(basename);
                        if (strmo!=null)
                        {
                            concurrentConnectionStringDic.AddOrUpdate(strmo.InitialCatalog.ToLower(), new Tuple<string, string>(strmo.ConnectStr, strmo.DataSource), (key, returnvalue) => returnvalue = new Tuple<string, string>(strmo.ConnectStr, strmo.DataSource));
                        }
                        else
                        {
                            LogFileWriteMessage.WriteLogs(MessageType.Error, "调用配置获取数据库链接地址错误，错误!");
                        }
                    }
                    //获取MQ数据通讯地址
                    var appmode = settingCenter.GetApplicationInfo("RabbitMQ");
                    if (appmode!=null)
                    {
                        //获取数据分析交互的MQ域配置
                        var mqconn = appmode.Properties.FirstOrDefault(mo => mo.Key == "CollectionAndAnalysisMQ");
                        if (!mqconn.Equals(default(KeyValuePair<string,Tuple<string,string>>)))
                        {
                            concurrentConnectionStringDic.AddOrUpdate(mqconn.Key.ToLower(), mqconn.Value, (key, returnvalue) => returnvalue = mqconn.Value);
                        }
                        else
                        {
                            LogFileWriteMessage.WriteLogs(MessageType.Error, "调用配置获取MQ通讯错误，错误消息为：在配置MQ集合中没有找到key=CollectionAndAnalysisMQ的MQ数据连接配置。");
                        }

                        ////获取机器学习的MQ域配置
                        //var mqconnMachine = appmode.Properties.FirstOrDefault(mo => mo.Key == "IntelligenceParagraphAnalysisMQ");
                        //if (!mqconnMachine.Equals(default(KeyValuePair<string, Tuple<string, string>>)))
                        //{
                        //    concurrentConnectionStringDic.AddOrUpdate(mqconnMachine.Key.ToLower(),mqconnMachine.Value,(key,retrunvalue)=>retrunvalue=mqconnMachine.Value );
                        //}
                        //else
                        //{
                        //    LogFileWriteMessage.WriteLogs(MessageType.Error, "调用配置获取MQ通讯错误，错误消息为：在配置MQ集合中没有找到key=IntelligenceParagraphAnalysisMQ的MQ数据连接配置。");
                        //}
                        //获取通用MQ交互域配置
                        var mqconnCommon = appmode.Properties.FirstOrDefault(mo => mo.Key == "CommonPlatform");
                        if (!mqconn.Equals(default(KeyValuePair<string, Tuple<string, string>>)))
                        {
                            concurrentConnectionStringDic.AddOrUpdate(mqconnCommon.Key.ToLower(), mqconnCommon.Value, (key, returnvalue) => returnvalue = mqconnCommon.Value);
                        }
                        else
                        {
                            LogFileWriteMessage.WriteLogs(MessageType.Error, "调用配置获取MQ通讯错误，错误消息为：在配置MQ集合中没有找到key=CommonPlatform的MQ数据连接配置。");
                        }
                    }
                    else
                    {
                        LogFileWriteMessage.WriteLogs(MessageType.Error, "调用配置获取MQ通讯错误，错误!");
                    }
                    List<string> appConfigUrl = new List<string>() { "WordParseAPI","Logstash","SystemAPI", "filemanage", "Ldt.ElementCenterInfoquery", "Ldt.ElementCenterFileStore","RuleParseServer","FileManager", "filecreateapi", "LawDataBase", "ArtificialIntelligence", "SwaggerUidAndPwd", "CauseDistinguish", "District", "uieextract", "LdtUserCenter" };
                    foreach (var appkey in appConfigUrl)
                    {
                        this.UpdateAppSettingInfo(appkey);
                    }
                }
                catch (Exception ex)
                {
                    LogFileWriteMessage.WriteLogs(MessageType.Error, "调用配置中心初始化错误，错误消息为：" + ex.Message);
                    LogFileWriteMessage.WriteLogs(MessageType.Error, "调用配置中心初始化错误，错误消```息为：" + ex.StackTrace);
                }
            }
            else if (ConfigManagerHandle.IsLoadLocalDataConfig)
            {
                //2019-03-15 ljx 加入如果配置为本地地址，则进行读取本地配置
                var settings = _configuration.GetSection("appSettings").GetChildren();
                if (settings != null)
                {
                    foreach (var itemsett in settings)
                    {//添加配置文件
                        appSetingDic.AddOrUpdate(itemsett.Key.ToLower(), new Tuple<string, string>(itemsett.Value, ""), (key, returnvalue) => returnvalue = new Tuple<string, string>(itemsett.Value, ""));
                    }
                }
                var connections = _configuration.GetSection("connectionStrings").GetChildren();
                if (connections != null)
                {
                    foreach (var itemcon in connections)
                    {
                        //加入数据库连接字符串
                        concurrentConnectionStringDic.AddOrUpdate(itemcon.Key.ToLower(), new Tuple<string, string>(itemcon.Value, ""), (key, returnvalue) => returnvalue = new Tuple<string, string>(itemcon.Value, ""));
                    }
                }
            }
        }

    }
}
